/*
 * TCSS 422 Web Spider Project
 * Group Money: Al McKenzie, Michael Pitts, Taylor Zielske
 */
package control.threads;

import model.URLInputCooker;
import model.URLStore;
import control.data.SearchHopper;

/**
 * This is a ThreadDirector that has the number of threads dedicated to buffering and
 * parsing specified at construction.
 * 
 * @author Michael Pitts
 * @version Nov 1, 2011
 */
public class ComplexMultiThreadDirector extends AbstractThreadDirector {
	
	/**
	 * The threads used by this Director.
	 */
	private final ProcessThread[] my_threads;

	/**
	 * Creates a new complex mutlithread director, which will allocate its threads to
	 * particular tasks, as indicated in the_threads.
	 * @param the_cooker is this program's URLInputCooker.
	 * @param the_hopper is this program's SearchHopper
	 * @param the_store is this program's URLStore
	 * @param the_search_words are the words to search on.
	 * @param the_threads indicates how many threads will be allocated to buffering
	 * and to parsing.  the_threads[0] == number of threads buffering, 
	 * the_threas[1] == number of threads parsing.
	 */
	public ComplexMultiThreadDirector(final URLInputCooker the_cooker,
			final SearchHopper the_hopper, final URLStore the_store,
			final String[] the_search_words, final int[] the_threads) {
		super(the_cooker, the_hopper, the_store, the_search_words);
		my_threads = new ProcessThread[the_threads[0] + the_threads[1]];
		for (int i = 0; i < the_threads[0]; i++) { // sets up buffer threads
			my_threads[i] = new ProcessThread(getCookOne());
			my_threads[i].setPriority(my_threads[i].getPriority() - 1);
		}
		for (int j = the_threads[0]; j < my_threads.length; j++) { // set up parse threads
			my_threads[j] = new ProcessThread(getParseOne());
			my_threads[j].setPriority(my_threads[j].getPriority() - 1);
		}
	}

	/**
	 * Gets a runnable that cooks one url, setting up its buffer.
	 * @return a new runnable that calls cookOne().
	 * @see AbstractThreadDirector#cookOne()
	 */
	private Runnable getCookOne() {
		return new Runnable() {
			@Override public void run() {
				cookOne(); // buffers one url
			}
		};
	}

	/**
	 * Gets a runnable that tries to parse one url, but may not be successful.
	 * @return a new runnable that calls parseOne().
	 * @see AbstractThreadDirector#parseOne()
	 */
	private Runnable getParseOne() {
		return new Runnable() {
			@Override public void run() {
				parseOne(); // tries to parse one url
			}
		};
	}

	/**
	 * {@inheritDoc}
	 */
	@Override public void start() {
		for (ProcessThread thread : my_threads) {
			thread.start();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override public void stop() {
		for (ProcessThread thread : my_threads) {
			thread.setGo(false);
		}
	}

}
